﻿import type { RequestOptions } from '@@/plugin-request/request';
import { RequestConfig, getRequestInstance } from '@umijs/max';
import { getAccessToken, getRefreshToken, setToken } from './utils/tokenManegerUtils';
import { refreshToken } from './services/auth';
import { handleAuthorized } from './utils/authUtils';
import { checkRespSuccessful } from './utils/serviceUtils';
import {
  API_BASE_URI,
  EXCLUDE_TOKEN_URI_LIST,
  LOGOUT_URI,
  REFRESH_TOKEN_URI,
  RespStatusCode,
} from './constants';

// 缓存的需要执行重新请求的列表
let requestList: (() => any)[] = [];
// 是否正在刷新中
let isRefreshToken = false;

/**
 * @name 错误处理
 * pro 自带的错误处理， 可以在这里做自己的改动
 * @doc https://umijs.org/docs/max/request#配置
 */
export const requestConfig: RequestConfig<API.Resp> = {
  baseURL: API_BASE_URI,
  // 请求拦截器
  requestInterceptors: [
    (config: RequestOptions) => {
      // 拦截请求配置，进行个性化处理。
      if (config.url && EXCLUDE_TOKEN_URI_LIST.includes(config.url)) {
        return config;
      }
      return {
        ...config,
        headers: {
          ...config.headers,
          Authorization: `Bearer ${getAccessToken()}`,
        },
      };
    },
  ],

  // 响应拦截器
  responseInterceptors: [
    // @ts-ignore
    async (response) => {
      if (
        response.status === 401 ||
        (typeof response.data === 'object' &&
          (response.data as API.Resp)?.code === RespStatusCode.UNAUTHORIZED)
      ) {
        // 对于登出的接口，直接返回响应值
        if (response.config.url?.includes(LOGOUT_URI)) {
          console.error('登出接口响应 401');
          requestList = [];
          isRefreshToken = false;
          return response;
        }

        if (response.config.url?.includes(REFRESH_TOKEN_URI)) {
          // 抛出异常，进入catch重定义到登录界面
          throw '更新 token 接口持续返回401';
        }

        if (!isRefreshToken) {
          isRefreshToken = true;
          try {
            // 更新 Token
            const refreshTokenStr = getRefreshToken();
            if (!refreshTokenStr) {
              // 抛出异常，进入catch重定义到登录界面
              throw '缺少 refreshToken，无法执行更新 token';
            }
            const res = await refreshToken(refreshTokenStr);
            if (!checkRespSuccessful(res) || !res.data) {
              // 抛出异常，进入catch重定义到登录界面
              throw '更新 token 接口响应错误';
            }
            setToken(res.data);
            requestList.forEach((fn) => fn());
            // 重新请求
            if (response.config.headers) {
              response.config.headers['Authorization'] = `Bearer ${getAccessToken()}`;
            }
            return getRequestInstance().request(response.config);
          } catch (err) {
            console.error(err);
            // requestList.forEach((fn) => fn());
            // 重定向到登录界面
            return handleAuthorized();
          } finally {
            requestList = [];
            isRefreshToken = false;
          }
        } else {
          return new Promise((resolve) => {
            requestList.push(() => {
              if (response.config.headers) {
                response.config.headers['Authorization'] = `Bearer ${getAccessToken()}`;
              }
              resolve(getRequestInstance().request(response.config));
            });
          });
        }
      }
      return response;
    },
  ],
};
